from collections import defaultdict  # 导入默认字典模块
from datetime import datetime, timedelta  # 导入日期时间模块

class EventTimeTumblingWindow:
    def __init__(self, size_sec: int=100, allowed_lateness_sec=0):
        """初始化事件时间滚动窗口"""
        self.size = timedelta(seconds=size_sec)  # 设置窗口大小（以秒为单位）
        self.lateness = timedelta(seconds=allowed_lateness_sec)  # 设置允许的延迟时间（以秒为单位）
        self.buffers = defaultdict(list)  # 初始化缓冲区，用于存储每个窗口的数据

    def assign_window(self, event_time: datetime) -> datetime:
        """根据事件时间分配窗口结束时间"""
        return datetime.min + (
            (event_time - datetime.min) # 计算窗口结束时间
            / self.size  # 计算事件时间所属的窗口编号
        ) * self.size + self.size  # 窗口结束时间 = 窗口编号 * 窗口大小 + 窗口大小

    def add_record(self, record: dict):
        """将记录添加到对应的窗口中"""
        window_end = self.assign_window(record['timestamp'])  # 根据记录的时间戳分配窗口结束时间
        self.buffers[window_end].append(record)  # 将记录添加到对应窗口的缓冲区中

    def check_trigger(self, watermark: datetime) -> list:
        """检查水印是否触发窗口计算，并返回触发的结果"""
        triggered = []  # 初始化触发结果的列表
        for window_end in list(self.buffers.keys()):  # 遍历所有窗口的结束时间
            if watermark >= window_end:  # 如果水印时间大于等于窗口结束时间，则触发窗口计算
                counts = defaultdict(int)  # 初始化计数器，用于统计每个单词的出现次数
                for r in self.buffers[window_end]:  # 遍历窗口中的所有记录
                    counts[r['word']] += r['count']  # 统计每个单词的出现次数
                triggered.append({  # 将触发结果添加到列表中
                    'window_end': window_end,  # 窗口结束时间
                    'results': [{'word': k, 'total': v} for k, v in counts.items()]  # 统计结果
                })
                del self.buffers[window_end]  # 删除已触发的窗口数据
        return triggered  # 返回所有触发的窗口结果